"""
批量视频处理核心模块
整合文件扫描、智能排序和视频合并功能
"""

import os
import logging
import time
import threading
from typing import List, Dict, Optional, Callable, Any
from dataclasses import dataclass, asdict
from enum import Enum
from pathlib import Path
import uuid
import json
from datetime import datetime

from .file_scanner import VideoFileScanner, VideoFileInfo, scan_video_folder
from .smart_sorter import SmartVideoSorter, SortMethod, analyze_video_naming
from .video_merger import VideoMerger, MergeConfig, MergeProgress, VideoQuality
from . import config


class ProcessStatus(Enum):
    """处理状态枚举"""
    PENDING = "pending"
    SCANNING = "scanning"
    ANALYZING = "analyzing"
    SORTING = "sorting"
    MERGING = "merging"
    COMPLETED = "completed"
    ERROR = "error"
    CANCELLED = "cancelled"


@dataclass
class BatchProcessTask:
    """批量处理任务"""
    task_id: str
    status: ProcessStatus
    input_path: str  # 输入文件夹路径或文件列表
    output_path: str  # 输出文件路径
    config: Dict[str, Any]  # 处理配置
    
    # 进度信息
    current_step: str = ""
    progress_percent: float = 0.0
    start_time: Optional[float] = None
    end_time: Optional[float] = None
    elapsed_time: float = 0.0
    estimated_remaining: float = 0.0
    
    # 结果数据
    scanned_files: List[VideoFileInfo] = None
    sorted_files: List[VideoFileInfo] = None
    merge_result: Dict = None
    error_message: str = ""
    
    # 统计信息
    total_files: int = 0
    valid_files: int = 0
    total_duration: float = 0.0
    total_size: int = 0
    
    def __post_init__(self):
        if self.scanned_files is None:
            self.scanned_files = []
        if self.sorted_files is None:
            self.sorted_files = []
        if self.merge_result is None:
            self.merge_result = {}


class BatchVideoProcessor:
    """批量视频处理器"""
    
    def __init__(self):
        self.logger = logging.getLogger(__name__)
        self.tasks: Dict[str, BatchProcessTask] = {}
        self.active_threads: Dict[str, threading.Thread] = {}
        
        # 组件初始化
        self.file_scanner = VideoFileScanner()
        self.smart_sorter = SmartVideoSorter()
    
    def create_task(self, input_path: str, output_path: str, 
                   config: Dict[str, Any] = None) -> str:
        """
        创建批量处理任务
        
        Args:
            input_path: 输入路径（文件夹或文件列表）
            output_path: 输出文件路径
            config: 处理配置
            
        Returns:
            任务ID
        """
        task_id = str(uuid.uuid4())
        
        default_config = {
            "sort_method": "natural",
            "merge_quality": "original",
            "recursive_scan": False,
            "max_file_size": 5 * 1024 * 1024 * 1024,  # 5GB
            "output_format": "mp4",
            "auto_start": True
        }
        
        if config:
            default_config.update(config)
        
        task = BatchProcessTask(
            task_id=task_id,
            status=ProcessStatus.PENDING,
            input_path=input_path,
            output_path=output_path,
            config=default_config
        )
        
        self.tasks[task_id] = task
        self.logger.info(f"创建批量处理任务: {task_id}")
        
        if default_config.get("auto_start", True):
            self.start_task(task_id)
        
        return task_id
    
    def create_task_with_file_data(self, file_data_path: str, output_path: str, 
                                  config: Dict[str, Any] = None) -> str:
        """
        使用完整文件数据创建批量处理任务
        
        Args:
            file_data_path: 包含完整视频文件信息的JSON文件路径
            output_path: 输出文件路径
            config: 处理配置
            
        Returns:
            任务ID
        """
        task_id = str(uuid.uuid4())
        
        default_config = {
            "sort_method": "natural",
            "merge_quality": "original",
            "recursive_scan": False,
            "max_file_size": 5 * 1024 * 1024 * 1024,  # 5GB
            "output_format": "mp4",
            "auto_start": True,
            "use_file_data": True  # 标记使用完整文件数据
        }
        
        if config:
            default_config.update(config)
        
        task = BatchProcessTask(
            task_id=task_id,
            status=ProcessStatus.PENDING,
            input_path=file_data_path,
            output_path=output_path,
            config=default_config
        )
        
        self.tasks[task_id] = task
        self.logger.info(f"创建批量处理任务（使用文件数据）: {task_id}")
        
        if default_config.get("auto_start", True):
            self.start_task(task_id)
        
        return task_id
    
    def start_task(self, task_id: str) -> bool:
        """
        启动任务
        
        Args:
            task_id: 任务ID
            
        Returns:
            是否启动成功
        """
        if task_id not in self.tasks:
            self.logger.error(f"任务不存在: {task_id}")
            return False
        
        task = self.tasks[task_id]
        
        if task.status != ProcessStatus.PENDING:
            self.logger.warning(f"任务已启动或完成: {task_id}")
            return False
        
        # 在新线程中执行任务
        thread = threading.Thread(target=self._execute_task, args=(task_id,))
        thread.daemon = True
        thread.start()
        
        self.active_threads[task_id] = thread
        
        self.logger.info(f"启动批量处理任务: {task_id}")
        return True
    
    def cancel_task(self, task_id: str) -> bool:
        """
        取消任务
        
        Args:
            task_id: 任务ID
            
        Returns:
            是否取消成功
        """
        if task_id not in self.tasks:
            return False
        
        task = self.tasks[task_id]
        task.status = ProcessStatus.CANCELLED
        task.end_time = time.time()
        
        # 注意：这里只是标记取消，实际的线程停止需要在执行过程中检查状态
        self.logger.info(f"取消批量处理任务: {task_id}")
        return True
    
    def get_task_status(self, task_id: str) -> Optional[Dict]:
        """
        获取任务状态
        
        Args:
            task_id: 任务ID
            
        Returns:
            任务状态信息
        """
        if task_id not in self.tasks:
            return None
        
        task = self.tasks[task_id]
        
        # 计算elapsed time
        if task.start_time:
            if task.end_time:
                task.elapsed_time = task.end_time - task.start_time
            else:
                task.elapsed_time = time.time() - task.start_time
        
        return {
            "task_id": task.task_id,
            "status": task.status.value,
            "current_step": task.current_step,
            "progress_percent": task.progress_percent,
            "elapsed_time": task.elapsed_time,
            "estimated_remaining": task.estimated_remaining,
            "total_files": task.total_files,
            "valid_files": task.valid_files,
            "total_duration": task.total_duration,
            "total_size": task.total_size,
            "error_message": task.error_message,
            "output_path": task.output_path if task.status == ProcessStatus.COMPLETED else None
        }
    
    def get_task_details(self, task_id: str) -> Optional[Dict]:
        """
        获取任务详细信息
        
        Args:
            task_id: 任务ID
            
        Returns:
            任务详细信息
        """
        if task_id not in self.tasks:
            return None
        
        task = self.tasks[task_id]
        
        return {
            **self.get_task_status(task_id),
            "input_path": task.input_path,
            "config": task.config,
            "scanned_files": [
                {
                    "filename": f.filename,
                    "path": f.path,
                    "size": f.size,
                    "duration": f.duration,
                    "resolution": f.resolution,
                    "format": f.format,
                    "is_valid": f.is_valid
                }
                for f in task.scanned_files
            ],
            "merge_result": task.merge_result
        }
    
    def list_tasks(self) -> List[Dict]:
        """
        列出所有任务
        
        Returns:
            任务列表
        """
        return [self.get_task_status(task_id) for task_id in self.tasks.keys()]
    
    def _execute_task(self, task_id: str):
        """执行任务的主流程"""
        task = self.tasks[task_id]
        
        try:
            task.start_time = time.time()
            task.status = ProcessStatus.SCANNING
            
            # 步骤1: 扫描文件
            self._update_task_progress(task, "扫描视频文件", 10)
            if not self._scan_files(task):
                return
            
            # 步骤2: 分析命名模式
            self._update_task_progress(task, "分析文件命名模式", 25)
            if not self._analyze_naming(task):
                return
            
            # 步骤3: 排序文件
            self._update_task_progress(task, "排序视频文件", 40)
            if not self._sort_files(task):
                return
            
            # 步骤4: 合并视频
            self._update_task_progress(task, "合并视频文件", 50)
            if not self._merge_videos(task):
                return
            
            # 完成
            task.status = ProcessStatus.COMPLETED
            task.end_time = time.time()
            self._update_task_progress(task, "处理完成", 100)
            
            self.logger.info(f"批量处理任务完成: {task_id}")
        
        except Exception as e:
            self.logger.error(f"任务执行失败: {task_id} - {e}")
            task.status = ProcessStatus.ERROR
            task.error_message = str(e)
            task.end_time = time.time()
        
        finally:
            # 清理线程引用
            if task_id in self.active_threads:
                del self.active_threads[task_id]
    
    def _scan_files(self, task: BatchProcessTask) -> bool:
        """扫描文件"""
        if task.status == ProcessStatus.CANCELLED:
            return False
        
        try:
            task.status = ProcessStatus.SCANNING
            
            # 设置扫描器参数
            self.file_scanner.max_file_size = task.config.get("max_file_size", 5 * 1024 * 1024 * 1024)
            
            # 扫描文件
            if os.path.isdir(task.input_path):
                # 扫描文件夹
                recursive = task.config.get("recursive_scan", False)
                video_files = self.file_scanner.scan_folder(task.input_path, recursive)
            else:
                # 处理文件列表（JSON格式）
                try:
                    with open(task.input_path, 'r') as f:
                        data = json.load(f)
                    
                    if task.config.get("use_file_data", False):
                        # 使用完整的文件数据（包括speed等信息）
                        video_files = []
                        for file_data in data:
                            # 从JSON数据创建VideoFileInfo对象
                            video_file = VideoFileInfo(
                                path=file_data.get("path", ""),
                                filename=file_data.get("filename", ""),
                                size=file_data.get("size", 0),
                                duration=file_data.get("duration", 0.0),
                                resolution=tuple(file_data.get("resolution", [0, 0])),
                                fps=file_data.get("fps", 0.0),
                                format=file_data.get("format", ""),
                                created_time=datetime.now(),  # 使用当前时间作为默认值
                                modified_time=datetime.now(),  # 使用当前时间作为默认值
                                is_valid=file_data.get("is_valid", True),
                                speed=file_data.get("speed", 1.0),  # 重要：获取speed参数
                                error_message=file_data.get("error_message")
                            )
                            video_files.append(video_file)
                    else:
                        # 传统方式：仅处理文件路径列表
                        video_files = self.file_scanner.scan_files(data)
                except:
                    # 作为单个文件处理
                    video_files = self.file_scanner.scan_files([task.input_path])
            
            task.scanned_files = video_files
            task.total_files = len(video_files)
            task.valid_files = len([f for f in video_files if f.is_valid])
            # 考虑速率调整后的总时长
            task.total_duration = sum(
                f.duration / (f.speed if hasattr(f, 'speed') and f.speed > 0 else 1.0) 
                for f in video_files if f.is_valid
            )
            task.total_size = sum(f.size for f in video_files if f.is_valid)
            
            if task.valid_files == 0:
                task.status = ProcessStatus.ERROR
                task.error_message = "没有找到有效的视频文件"
                return False
            
            self.logger.info(f"扫描完成: {task.valid_files}/{task.total_files} 个有效文件")
            return True
        
        except Exception as e:
            task.status = ProcessStatus.ERROR
            task.error_message = f"文件扫描失败: {str(e)}"
            return False
    
    def _analyze_naming(self, task: BatchProcessTask) -> bool:
        """分析命名模式"""
        if task.status == ProcessStatus.CANCELLED:
            return False
        
        try:
            task.status = ProcessStatus.ANALYZING
            
            # 分析命名模式
            analysis = self.smart_sorter.analyze_naming_pattern(task.scanned_files)
            
            # 根据分析结果调整排序方法
            if analysis.get("confidence", 0) > 0.7:
                recommended_method = analysis.get("recommended_method", SortMethod.NATURAL)
                if "sort_method" not in task.config or task.config["sort_method"] == "auto":
                    task.config["sort_method"] = recommended_method.value
            
            self.logger.info(f"命名模式分析完成: confidence={analysis.get('confidence', 0):.2f}")
            return True
        
        except Exception as e:
            task.status = ProcessStatus.ERROR
            task.error_message = f"命名模式分析失败: {str(e)}"
            return False
    
    def _sort_files(self, task: BatchProcessTask) -> bool:
        """排序文件"""
        if task.status == ProcessStatus.CANCELLED:
            return False
        
        try:
            task.status = ProcessStatus.SORTING
            
            # 获取排序方法
            sort_method_str = task.config.get("sort_method", "natural")
            try:
                sort_method = SortMethod(sort_method_str)
            except ValueError:
                sort_method = SortMethod.NATURAL
            
            # 排序文件
            valid_files = [f for f in task.scanned_files if f.is_valid]
            sorted_files = self.smart_sorter.sort_videos(valid_files, sort_method)
            
            task.sorted_files = sorted_files
            
            self.logger.info(f"文件排序完成: {len(sorted_files)} 个文件")
            return True
        
        except Exception as e:
            task.status = ProcessStatus.ERROR
            task.error_message = f"文件排序失败: {str(e)}"
            return False
    
    def _merge_videos(self, task: BatchProcessTask) -> bool:
        """合并视频"""
        if task.status == ProcessStatus.CANCELLED:
            return False
        
        try:
            task.status = ProcessStatus.MERGING
            
            # 创建输出目录
            output_dir = os.path.dirname(task.output_path)
            if output_dir and not os.path.exists(output_dir):
                os.makedirs(output_dir)
            
            # 配置合并器
            quality_str = task.config.get("merge_quality", "original")
            try:
                quality = VideoQuality(quality_str)
            except ValueError:
                quality = VideoQuality.ORIGINAL
            
            merge_config = MergeConfig(
                quality=quality,
                output_format=task.config.get("output_format", "mp4"),
                temp_dir=config.WORK_DIR,
                # 背景音乐配置
                background_music_path=task.config.get("background_music_path"),
                background_music_volume=task.config.get("background_music", {}).get("volume", 0.3) if task.config.get("background_music") else 0.3,
                background_music_fade=task.config.get("background_music", {}).get("fade", "in") if task.config.get("background_music") else "in",
                background_music_start_time=task.config.get("background_music", {}).get("start_time", 0.0) if task.config.get("background_music") else 0.0
            )
            
            merger = VideoMerger(merge_config)
            
            # 设置进度回调
            def progress_callback(progress: MergeProgress):
                if task.status == ProcessStatus.CANCELLED:
                    return
                
                # 合并进度占总进度的50%（从50%到100%）
                merge_progress = 50 + (progress.progress_percent * 0.5)
                self._update_task_progress(task, progress.current_operation, merge_progress)
            
            merger.set_progress_callback(progress_callback)
            
            # 执行合并
            result = merger.merge_videos(task.sorted_files, task.output_path)
            
            task.merge_result = result
            
            if not result.get("success", False):
                task.status = ProcessStatus.ERROR
                task.error_message = result.get("error", "视频合并失败")
                return False
            
            self.logger.info(f"视频合并完成: {task.output_path}")
            return True
        
        except Exception as e:
            task.status = ProcessStatus.ERROR
            task.error_message = f"视频合并失败: {str(e)}"
            return False
    
    def _update_task_progress(self, task: BatchProcessTask, step: str, progress: float):
        """更新任务进度"""
        task.current_step = step
        task.progress_percent = min(progress, 100.0)
        
        # 估算剩余时间
        if task.start_time and progress > 0:
            elapsed = time.time() - task.start_time
            if progress < 100:
                total_estimated = elapsed * (100 / progress)
                task.estimated_remaining = total_estimated - elapsed
            else:
                task.estimated_remaining = 0
        
        self.logger.debug(f"任务进度 {task.task_id}: {step} ({progress:.1f}%)")


# 便捷函数
def process_video_folder(folder_path: str, output_path: str, 
                        config: Dict[str, Any] = None) -> str:
    """
    便捷函数：处理视频文件夹
    
    Args:
        folder_path: 文件夹路径
        output_path: 输出文件路径
        config: 处理配置
        
    Returns:
        任务ID
    """
    processor = BatchVideoProcessor()
    return processor.create_task(folder_path, output_path, config)


def get_processing_status(task_id: str) -> Optional[Dict]:
    """
    便捷函数：获取处理状态
    
    Args:
        task_id: 任务ID
        
    Returns:
        状态信息
    """
    # 这里需要全局的processor实例
    # 在实际使用中，应该通过单例模式或依赖注入来管理
    pass


# 全局处理器实例（单例模式）
_global_processor = None

def get_global_processor() -> BatchVideoProcessor:
    """获取全局处理器实例"""
    global _global_processor
    if _global_processor is None:
        _global_processor = BatchVideoProcessor()
    return _global_processor
